#include "nrf24l01.h"

unsigned char tempdata;
unsigned char IO;
unsigned char PIN;
unsigned char Register = 0;
unsigned char CSN = BIT3;
unsigned char CE = BIT4;
unsigned char SOMI = BIT6;
unsigned char SIMO = BIT7;
unsigned char SCLK = BIT5;
unsigned char TxAdd[5];//DELAY 5ms


void Nordic_Init(unsigned char RX)
{
	P1DIR |= CSN + CE;
	P1OUT |= CSN;

	SPI_Init(SCLK, SOMI, SIMO);
	Nordic_csh();
	//Nordic_InitDefault(RX);
}

void Nordic_InitDefault(unsigned char RX)
{
	unsigned char Rx0[5]={0xE7,0xE7,0xE7,0xE7,0xE7};
	unsigned char Rx1[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
	unsigned char Tx[5]={0xE7,0xE7,0xE7,0xE7,0xE7};

 	P1DIR |= CSN + CE;
	P1OUT |= CSN;

	SPI_Init(SCLK, SOMI, SIMO);
	Nordic_csh();
 
 if(RX==0x01)
		Nordic_WriteCommand(0x00,0x0B);
	else
		Nordic_WriteCommand(0x00,0x0A);

	Nordic_WriteCommand(0x01,0x00); //EN_AA
	Nordic_WriteCommand(0x02,0x03); //EN RX ADDR
	Nordic_WriteCommand(0x03,0x03); //SETUP AW
	Nordic_WriteCommand(0x04,0x03); //SETUP RETR
	Nordic_WriteCommand(0x05,0x02); //RF CH
	Nordic_WriteCommand(0x06,0x0F); //RF SETUP
	//Nordic_WriteCommand(0x07,0x0F); //STATUS
	//Nordic_WriteCommand(0x08,0x4F); //OBSERVE TX; DEFAULT VALUE
	//Nordic_WriteCommand(0x09,0x4F); //RPD; DEFAULT VALUE
	Nordic_SetRxChannel0(Rx0); //RXADDR P0 (Reg: 0x0A)
	Nordic_SetRxChannel1(Rx1); //RXADDR P1 (Reg: 0X0B)
	Nordic_WriteCommand(0x0C,0xC3); //RXADDR P2
	Nordic_WriteCommand(0x0D,0xC4); //RXADDR P3
	Nordic_WriteCommand(0x0E,0xC5); //RXADDR P4
	Nordic_WriteCommand(0x0F,0xC6); //RXADDR P5
	Nordic_SetTxChannel(Tx);//TXADDR

}

/*****************************************************************************************
 * Chip Enable
 *
 * TBD
*****************************************************************************************/
void Nordic_ChipEnable()
{
	P1OUT |= CE;
}

/*****************************************************************************************
 * Chip disable
 *
 * TBD
*****************************************************************************************/
void Nordic_ChipDisable()
{
	P1OUT &= ~CE;
}

void Nordic_Transmit()
{
	Nordic_ChipEnable();
	DelayUS(10);
	Nordic_ChipDisable();
}


/*****************************************************************************************
 * Data and Control Interface
 *
 * There are 11 data and control commands:
 * (R_REGISTER)
 * (W_REGISTER)
 * (R_RX_PAYLOAD)	
 * (R_TX_PAYLOAD)	
 * (FLUSH_TX)
 * (FLUSH_RX)
 * (REUSE_TX_PL)
 * (R_RX_PL_WID)
 * (W_ACK_PAYLOAD)	//NOT IMPLEMENTED YET
 * (W_TX_PAYLOAD_NOACK)	//NOT IMPLEMENTED YET
 * (NOP)
*****************************************************************************************/

void Nordic_ReadRegisters(unsigned char Address, unsigned char * data, unsigned int len)
{
	unsigned int i;

	Nordic_csl();
	SPI_Transfer(Address);

	for(i = 0; i < len; i++)
	{
		data[i]=SPI_Transfer(NORDIC_NOP);
	}

	Nordic_csh();
}

void Nordic_WriteRegisters(unsigned char Address, unsigned char * data, unsigned int len)
{
	unsigned int i;

	Nordic_csl();
	SPI_Transfer(Address);

	for(i = 0; i < len; i++)
	{
		SPI_Transfer(data[i]);
	}

	Nordic_csh();
}

//Will become obsolete
unsigned char Nordic_ReadCommand(unsigned char Data)
{
	unsigned char Result;

	Nordic_csl();
	Result = SPI_Transfer(Data);
	Result = SPI_Transfer(NORDIC_NOP);
	Nordic_csh();

	return Result;
}

//Will become obsolete
void Nordic_WriteCommand(unsigned char Address, unsigned char Data)
{
	Register = NORDIC_W_REGISTER|Address;

	Nordic_csl();
	SPI_Transfer(Register);
	SPI_Transfer(Data);
	Nordic_csh();
}


void Nordic_ReadPayload(unsigned char* Data)
{
	unsigned char Result;

	Result = Nordic_ReadPayloadWidth();
	Nordic_ReadRegisters(NORDIC_R_RX_PAYLOAD, Data, Result);
}

void Nordic_WritePayload(unsigned char* Data, unsigned int len)
{
	Nordic_WriteRegisters(NORDIC_W_TX_PAYLOAD, Data, len);
	Nordic_Transmit();
}

void Nordic_FlushTx()
{
	Nordic_csl();
	SPI_Transfer(NORDIC_FLUSH_TX);
	Nordic_csh();
}

void Nordic_FlushRx()
{
	Nordic_csl();
	SPI_Transfer(NORDIC_FLUSH_RX);
	Nordic_csh();
}

void Nordic_ReuseTxPL()
{
	Nordic_csl();
	SPI_Transfer(NORDIC_REUSE_TX_PL);
	Nordic_csh();
}

unsigned char Nordic_ReadPayloadWidth()
{
	unsigned char Result;

	Nordic_csl();
	Result = SPI_Transfer(NORDIC_R_RX_PAYLOAD);
	Result = SPI_Transfer(NORDIC_NOP);
	Nordic_csh();

	return Result;
}


void Nordic_NoOperation()
{
	Nordic_csl();
	SPI_Transfer(NORDIC_NOP);
	Nordic_csh();
}

/*****************************************************************************************
 * Configuration Register (0x00)
 *
 * Configuration:
 * Mask interrupt (NOT IMPLEMENTED)
 * Enable CRC16
 * Power up
 * Power Down
 * RX control
 * TX control
*****************************************************************************************/

unsigned char Nordic_GetConfig()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	return Result;
}

void Nordic_CRC16()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	Nordic_WriteCommand(NORDIC_CONFIG, Result|BIT2);
}

void Nordic_PowerUp()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	Nordic_WriteCommand(NORDIC_CONFIG, Result|BIT1);
}

void Nordic_PowerDown()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	Nordic_WriteCommand(NORDIC_CONFIG, Result&(~BIT1));
}

void Nordic_RxMode()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	Nordic_WriteCommand(NORDIC_CONFIG, Result|BIT0);
	Nordic_ChipEnable(); //Possibly change this to a variable; active monitoring
}

void Nordic_TxMode()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_CONFIG);
	Nordic_WriteCommand(NORDIC_CONFIG, Result&(~BIT0));
	Nordic_ChipDisable(); //Possibly change this to a variable; active monitoring
}

/*****************************************************************************************
 * Enable AA (0x02)
 * void Nordic_EnableAA(unsigned char Data)
 *
 * Enable RX addresses
 ****************************************************************************************/
void Nordic_EnableAA(unsigned char Data)
{
	Nordic_WriteCommand(NORDIC_EN_AA, Data);
}

/*****************************************************************************************
 * Set Address Width (0x03)
 *
 * void Nordic_SetAddressWidth(unsigned char Width)
 *
 * Setup the address width (common for all data pipes)
 * '00' - illegal
 * '01' - 3 bytes
 * '10' - 4 bytes
 * '11' - 5 bytes
*****************************************************************************************/
void Nordic_SetAddressWidth(unsigned char Width)
{
	Nordic_WriteCommand(NORDIC_SETUP_AW, Width);
}

/*****************************************************************************************
 * RF Channel (0x05)
 *
 * Sets the frequency channel nRF24L01+ operates on
 * It can only be 7bits long
*****************************************************************************************/
void Nordic_SetRFChannel(unsigned char Channel)
{
	Nordic_WriteCommand(NORDIC_RF_CH, Channel);
}

unsigned char Nordic_GetRFChannel()
{
	unsigned char Result;
	Result = Nordic_ReadCommand(NORDIC_RF_CH);
	return Result;
}

/*****************************************************************************************
 * RF Setup (0x06)
 *
 * CONT_WAVE //NOT IMPLEMENTED
 * RF_DR_LOW //NOT IMPLEMENTED
 * PLL_LOCK //NOT IMPLEMENTED
 * RF_DR_HIGH //NOT IMPLEMENTED
 * RF_PWR - sets output power in TX mode //NOT IMPLEMENTED
*****************************************************************************************/
void Nordic_SetRFSetup(unsigned char Data)
{
	Nordic_WriteCommand(NORDIC_RF_SETUP, Data);
}

/*****************************************************************************************
 * Status (0x07)
 *
 * TBD
*****************************************************************************************/
unsigned char Nordic_GetStatus()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_STATUS);
	return Result;
}

void Nordic_ClearInterrupts()
{
	unsigned char Result;

	Result = Nordic_ReadCommand(NORDIC_STATUS);
	Nordic_WriteCommand(NORDIC_STATUS, Result|(BIT4+BIT5+BIT6));
}

//returns true if IRQ pin is low, false otherwise
unsigned char Nordic_IRQ()
{
	if((P2IN & BIT0) != 0)
		return false;
	else
		return true;
}

//returns true if RX_DR interrupt is active, false otherwise
unsigned char Nordic_IrqRx()
{
	return (Nordic_GetStatus() & BIT6);
}

//returns true if TX_DS interrupt is active, false otherwise
unsigned char Nordic_IrqTx()
{
	return (Nordic_GetStatus() & BIT5);
}

//returns true if MAX_RT interrupt is active, false otherwise
unsigned char Nordic_IrqMaxRT()
{
	return (Nordic_GetStatus() & BIT4);
}



/*****************************************************************************************
*RX Address (0x0A-0x0F)
* Unfinished, not working code
*
*****************************************************************************************/
void Nordic_RxAddress(unsigned char Channel, unsigned char Length, unsigned long Address)
{
	unsigned char Result;
	unsigned char Length2;

	//Result = Nordic_ReadCommand(NORDIC_CONFIG);
	if(Channel==0)
	{
		Nordic_csl();
	SPI_Transfer(NORDIC_RX_ADDR_P0);
	//SPI_Transfer(Data);
	Result = Address;
	SPI_Transfer(Result);
    Result = Address>>8;
	SPI_Transfer(Result);
	Result = Address>>16;
	SPI_Transfer(Result);
	Result = Address>>24;
	SPI_Transfer(Result);
	Result = Address>>30;
	SPI_Transfer(Result);
	Nordic_csh();
	}
	else if(Channel==1)
	{
		//Result = SPI_WriteRegisters(RX_ADDR_P1, Length, 4);

	}
	else
	{
		//Result = SPI_WriteRegisters((Channel+10), Length2, 1);

	}
}


/*****************************************************************************************
* RX Address (0x0A-0x0F)
* Unfinished, not working code
*
*****************************************************************************************/
void Nordic_getRxAddress(unsigned char Channel)
{
	unsigned char Result;
	unsigned char Length2;

	//Result = Nordic_ReadCommand(NORDIC_CONFIG);
	if(Channel==0)
	{
		uart_puts((char *)"NRF24l01 address: ");

		Nordic_csl();
		Result = SPI_Transfer(NORDIC_RX_ADDR_P0);
		Result = SPI_Transfer(NORDIC_NOP);
		printreg((char *)" ", Result);
		Result = SPI_Transfer(NORDIC_NOP);
		printreg((char *)" ", Result);
		Result = SPI_Transfer(NORDIC_NOP);
		printreg((char *)" ", Result);
		Result = SPI_Transfer(NORDIC_NOP);
		printreg((char *)" ", Result);
		Result = SPI_Transfer(NORDIC_NOP);
		printreg((char *)" ", Result);
		Nordic_csh();
	}
	else if(Channel==1)
	{
		//Result = SPI_WriteRegisters(RX_ADDR_P1, Length, 4);

	}
	else
	{
		//Result = SPI_WriteRegisters((Channel+10), Length2, 1);

	}
}

//TEMPORARY FUNCTION
void Nordic_SetRxChannel0(unsigned char* Address)
{
	Nordic_WriteRegisters(NORDIC_W_REGISTER|(0x0A), Address, 5);
}
//TEMPORARY FUNCTION
void Nordic_SetRxChannel1(unsigned char* Address)
{
	Nordic_WriteRegisters(NORDIC_W_REGISTER|(0x0B), Address, 5);
}

//Untested code; should replace the two temporary functions above.
void Nordic_SetRxAddress(unsigned char Channel, unsigned char* Address)
{
	unsigned char Reg;
	unsigned char Length2;

	Reg = 0x0A + Channel;
	//Result = Nordic_ReadCommand(NORDIC_CONFIG);
	if(Channel==0 || Channel==1)
	{
		Nordic_WriteRegisters(NORDIC_W_REGISTER|Reg, Address, 5);
	}
	else if(Channel<6)
	{
		Nordic_WriteRegisters(NORDIC_W_REGISTER|Reg, Address, 1);
	}
	else
	{
		//Log error
	}
}


/*****************************************************************************************
* TX Address (0x10)
*
* Transmit address
*****************************************************************************************/
void Nordic_SetTxChannel(unsigned char* Address)
{
	Nordic_WriteRegisters(NORDIC_W_REGISTER|(0x10), Address, 5);
}

/*****************************************************************************************
 * Received Payload Width (0x11-0x16)
 *
 * void Nordic_RxPayloadLength(unsigned char Channel, unsigned char Width)
 *
 * Setup the receive payload width for specific data pipe channel
*****************************************************************************************/
void Nordic_RxPayloadLength(unsigned char Channel, unsigned char Width)
{
	Nordic_WriteCommand((Channel+17), Width);
}

/*****************************************************************************************
 * FIFO Status (0x17)
 *
 * TX_REUSE
 * TX_FULL
 * TX_EMPTY
 * RX_FULL
 * RX_EMPTY
*****************************************************************************************/
unsigned char Nordic_GetFIFOStatus()
{
	return Nordic_ReadCommand(NORDIC_FIFO_STATUS);
}
unsigned char Nordic_GetStatus_TXReuse()
{
	unsigned char status;
	status =  Nordic_ReadCommand(NORDIC_FIFO_STATUS);
	status &= BIT6;
	return status;
}
unsigned char Nordic_GetStatus_TXFull()
{
	unsigned char status;
	status =  Nordic_ReadCommand(NORDIC_FIFO_STATUS);
	status &= BIT5;
	return status;
}
unsigned char Nordic_GetStatus_TXEmpty()
{
	unsigned char status;
	status =  Nordic_ReadCommand(NORDIC_FIFO_STATUS);
	status &= BIT4;
	return status;
}
unsigned char Nordic_GetStatus_RXFull()
{
	unsigned char status;
	status =  Nordic_ReadCommand(NORDIC_FIFO_STATUS);
	status &= BIT1;
	return status;
}
unsigned char Nordic_GetStatus_RXEmpty()
{
	unsigned char status;
	status =  Nordic_ReadCommand(NORDIC_FIFO_STATUS);
	status &= BIT0;
	return status;
}

void Nordic_csh(void)
{
    P1OUT |= CSN;
}

void Nordic_csl(void)
{
    P1OUT &= ~CSN;
}
